﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading.Tasks;

namespace FindDuplicateFile
{
    public class FSNodeBuilder
    {
        public static FSDirectoryNode GetExplorerSystem(string sPath, string searchExtension, IWorkInProgress wip = null)
        {
            if (wip != null)
                wip.BeginWork("Analyse des dossiers");

            DirectoryInfo dinfo = new DirectoryInfo(sPath);
            FSDirectoryNode FileSystemRoot = FSDirectoryNode.CreateFSDirectoryNode(null, dinfo, "*." + searchExtension, wip);

            if (wip != null)
                wip.EndWork("Analyse des dossiers terminé");

            return FileSystemRoot;
        }

        /// <summary>
        /// Retourne une liste avec tous les dossiers et sous dossier du dossier courant
        /// Il s'agit donc d'une mise a plat de l'arbo des dossiers
        /// RECURSIF
        /// Implementation du parcousr de l'arbo des dossiers pour mise a plat
        /// </summary>
        public static List<FSDirectoryNode> GetDirectorySystem(FSDirectoryNode CurrentDir,IWorkInProgress wip = null)
        {
            if (wip != null)
                wip.BeginWork("Analyse des dossiers");

            List<FSDirectoryNode> lst = new List<FSDirectoryNode>();
            lst.Add(CurrentDir);
            foreach (FSDirectoryNode dirNode in CurrentDir.Directories)
            {
                lst.AddRange(GetDirectorySystem(dirNode,null));
                if (wip != null)
                    wip.AdvanceWork();
            }

            if (wip != null)
                wip.EndWork("Analyse des dossiers terminé");

            return lst;
        }

        /// <summary>
        /// Retourne une liste avec tous les fichiers de tous les dossiers 
        /// Il s'agit donc d'une mise a plat de l'arbo des fichiers
        /// RECURSIF
        /// Implementation du parcousr de l'arbo des dossiers pour mise a plat
        /// </summary>
        public static List<FSFileNode> GetFilesSystem(FSDirectoryNode CurrentDir, IWorkInProgress wip = null)
        {
            if (wip != null)
                wip.BeginWork("Analyse des fichiers");

            List<FSFileNode> lst = CurrentDir.Files.ToList();
            foreach (FSDirectoryNode dirNode in CurrentDir.Directories)
            {
                lst.AddRange(GetFilesSystem(dirNode));
                if (wip != null)
                    wip.AdvanceWork();
            }

            if (wip != null)
                wip.EndWork("Analyse des fichiers terminé");

            return lst;
        }

        /// <summary>
        /// Retourne une liste avec tous les fichiers de tous les dossiers 
        /// Il s'agit donc d'une mise a plat de l'arbo des fichiers
        /// RECURSIF
        /// Implementation du parcousr de l'arbo des dossiers pour mise a plat
        /// </summary>
        public static List<FSFileNode> GetDuplicateFiles(List<FSFileNode> lstFiles, IWorkInProgress wip = null)
        {
            if (wip != null)
                wip.BeginWork("Calcule clé de hash",lstFiles.Count+1);

            Parallel.ForEach<FSFileNode>(lstFiles,
                (node) =>
                {
                    node.ComputeFileMD5Hash();

                    if (wip != null)
                        wip.AdvanceWork(1);
                });

            if (wip != null)
                wip.AdvanceWork("Recherche des fichiers dupliqué",1);

            List<FSFileNode> lst = lstFiles.GroupBy(i => i.MD5Hash)
                                .Where(g => g.Count() > 1)
                                .SelectMany(list => list)
                                .ToList();

            if (wip != null)
                wip.EndWork("Analyse des fichiers dupliqués terminé");

            return lst;
        }

    }
}
